package cn.com.zero.common.message.util;

import cn.com.zero.common.message.cache.MessageCacheRedis;
import cn.com.zero.common.message.config.properties.MessageProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @author xiongxj
 * @version 1.0.0
 * @Description 消息防火墙工具类
 * @createTime 2023/2/27 14:13
 */
@Component
public class SendMessageUtil {
    private static Logger logger = LoggerFactory.getLogger(SendMessageUtil.class);

    private MessageCacheRedis messageCache;
    private MessageProperties messageProperties;
    /**
     * 随机数生成器
     */
    private static Random random = new Random();

    /**
     * 检查是否发送信息
     *
     * @param phoneNumber 手机号
     * @param messageType    消息类型
     * @param ip          ip地址
     * @return true：发送信息；false：不发送信息
     */
    public boolean checkSendMessage(String phoneNumber, String messageType, String ip, Integer repeat_send_time) {
        // 检查ip发送短信次数是否达到上限；0.0.0.0 系统ip不检查上限
        if (!"0.0.0.0".equals(ip)) {
            Integer sendNum = messageCache.getIpSendNum(ip);
            if (sendNum >= messageProperties.getMaxSendNumByIp()) {
                logger.warn("IP地址[{}]发送短信次数[{}]已经达到上限次数[{}]", ip, sendNum, messageProperties.getMaxSendNumByIp());
                return false;
            }
        }

        // 检查不在白名单中的手机号是否允许发送短信
        List<String> whiteList = messageProperties.getPhoneWhiteList();
        if (whiteList == null || whiteList.size() == 0 || !whiteList.contains(phoneNumber)) {
            // 检查手机号发送短信次数是否达到上限
            Integer sendNum = messageCache.getPhoneSendNum(phoneNumber);
            if (sendNum >= messageProperties.getMaxSendNumByPhone()) {
                logger.warn("手机号[{}]发送短信次数[{}]已经达到上限次数[{}]", phoneNumber, sendNum, messageProperties.getMaxSendNumByPhone());
                return false;
            }

            // 检查消息类型和手机号上次发送时间和现在时间差是否超过再次发送时间
            if (repeat_send_time != null) {
                Date preSendTime = messageCache.getPreSendVerificationCodeTime(phoneNumber, messageType);
                if (preSendTime != null) {
                    long diffTime = System.currentTimeMillis() - preSendTime.getTime();
                    if (diffTime < repeat_send_time * 1000L) {
                        logger.info("向手机号[{}]发送类型为[{}]验证码时，距离上次发送短信时间[{}]秒尚未超过阈值[{}]秒，不能再次发送短信", phoneNumber, messageType, diffTime / 1000, repeat_send_time);
                        return false;
                    }
                }
            }
        }
        return true;
    }

    /**
     * 生成验证码
     *
     * @param codeLength 验证码长度
     * @return 验证码
     */
    public String generateVerificationCode(Integer codeLength) {
        StringBuilder verificationCode = new StringBuilder();
        for (int i = 0; i < codeLength; i++) {
            int n = random.nextInt(10);
            while (i == 0 && n == 0) {
                n = random.nextInt(10);
            }
            verificationCode.append(n);
        }
        return verificationCode.toString();
    }

    public MessageProperties getMessageProperties() {
        return messageProperties;
    }

    @Autowired
    public void setMessageCache(MessageCacheRedis messageCache) {
        this.messageCache = messageCache;
    }

    @Autowired
    public void setMessageProperties(MessageProperties messageProperties) {
        this.messageProperties = messageProperties;
    }
}
